/**************************************************************************** 
* 
* Copyright (c) 2023  C*Core -   All Rights Reserved  
* 
* THIS SOFTWARE IS DISTRIBUTED "AS IS," AND ALL WARRANTIES ARE DISCLAIMED, 
* INCLUDING MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* 
* PROJECT     : CCFC2011BC           
* DESCRIPTION : CCFC2011BC can low level drivers code 
* HISTORY     : Initial version.
* @file     can_lld.h
* @version  1.1
* @date     2023 - 02 - 20
* @brief    Initial version.
*
*****************************************************************************/
#ifndef CAN_LLD_H_
#define CAN_LLD_H_

#include "CCFC2011BC.h"
#include "common.h"
#include "lldconf.h"
#include "intc_lld.h"
#include "sys.h"
#include "console.h"

#ifndef NULL
#define NULL 0
#endif

#ifndef ENABLE
#define ENABLE 1
#endif
#ifndef DISABLE
#define DISABLE 0
#endif

#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif

#define BIT_GET(_word, _pos) ((_word) & (1UL << (_pos))) /* PRQA S 3472 # simple macro function */
#define BIT_SET(_word, _pos) ((_word) |= (1UL << (_pos))) /* PRQA S 3472 # simple macro function */
#define BIT_CLR(_word, _pos) ((_word) &= (~(1UL << (_pos)))) /* PRQA S 3472 # simple macro function */

#define CAN_TOTAL_MAIL_BOX_NUM 64U
#define CAN_FIFO_USE_MAIL_BOX_NUM 8U
#define CAN_FIFO_FILTER_TABLE_NUM 8U
#define CAN_WORD_INDICATE_MAIL_BOX_NUM 32U

#define CAN_TX_MB_STATE_INACTIVE 8U
#define CAN_TX_MB_STATE_ABORT_TRANS_CUR_MSG 9U
#define CAN_TX_MB_STATE_START_TRANS_DATA_MSG 12U
#define CAN_TX_MB_STATE_AFTER_TRANS_DATA_MSG 8U
#define CAN_TX_MB_STATE_START_TRANS_REMOTE_MSG 12U
#define CAN_TX_MB_STATE_WAIT_REMOTE_MSG 10U
#define CAN_TX_MB_STATE_RECVED_REMOTE_MSG 14U
#define CAN_TX_MB_STATE_RESPONSE_REMOTE_MSG 10U

#define CAN_RX_MB_STATE_INACTIVE 0U
#define CAN_RX_MB_STATE_WAIT_MSG 4U
#define CAN_RX_MB_STATE_RECVED_MSG 2U
#define CAN_RX_MB_STATE_OVERWRITTEN 6U

#define CAN_MOD_ID_0_ESR_ERROR_INT_NUM      65U
#define CAN_MOD_ID_0_ESR_BUS_OFF_INT_NUM    66U
#define CAN_MOD_ID_0_MSG_00_03_INT_NUM      68U
#define CAN_MOD_ID_0_MSG_04_07_INT_NUM      69U
#define CAN_MOD_ID_0_MSG_08_11_INT_NUM      70U
#define CAN_MOD_ID_0_MSG_12_15_INT_NUM      71U
#define CAN_MOD_ID_0_MSG_16_31_INT_NUM      72U
#define CAN_MOD_ID_0_MSG_32_63_INT_NUM      73U

#define CAN_MOD_ID_1_ESR_ERROR_INT_NUM      85U
#define CAN_MOD_ID_1_ESR_BUS_OFF_INT_NUM    86U
#define CAN_MOD_ID_1_MSG_00_03_INT_NUM      88U
#define CAN_MOD_ID_1_MSG_04_07_INT_NUM      89U
#define CAN_MOD_ID_1_MSG_08_11_INT_NUM      90U
#define CAN_MOD_ID_1_MSG_12_15_INT_NUM      91U
#define CAN_MOD_ID_1_MSG_16_31_INT_NUM      92U
#define CAN_MOD_ID_1_MSG_32_63_INT_NUM      93U

#define CAN_MOD_ID_2_ESR_ERROR_INT_NUM      105U
#define CAN_MOD_ID_2_ESR_BUS_OFF_INT_NUM    106U
#define CAN_MOD_ID_2_MSG_00_03_INT_NUM      108U
#define CAN_MOD_ID_2_MSG_04_07_INT_NUM      109U
#define CAN_MOD_ID_2_MSG_08_11_INT_NUM      110U
#define CAN_MOD_ID_2_MSG_12_15_INT_NUM      111U
#define CAN_MOD_ID_2_MSG_16_31_INT_NUM      112U
#define CAN_MOD_ID_2_MSG_32_63_INT_NUM      113U

#define CAN_MOD_ID_3_ESR_ERROR_INT_NUM      173U
#define CAN_MOD_ID_3_ESR_BUS_OFF_INT_NUM    174U
#define CAN_MOD_ID_3_MSG_00_03_INT_NUM      176U
#define CAN_MOD_ID_3_MSG_04_07_INT_NUM      177U
#define CAN_MOD_ID_3_MSG_08_11_INT_NUM      178U
#define CAN_MOD_ID_3_MSG_12_15_INT_NUM      179U
#define CAN_MOD_ID_3_MSG_16_31_INT_NUM      180U
#define CAN_MOD_ID_3_MSG_32_63_INT_NUM      181U

#define CAN_MOD_ID_4_ESR_ERROR_INT_NUM      190U
#define CAN_MOD_ID_4_ESR_BUS_OFF_INT_NUM    191U
#define CAN_MOD_ID_4_MSG_00_03_INT_NUM      193U
#define CAN_MOD_ID_4_MSG_04_07_INT_NUM      194U
#define CAN_MOD_ID_4_MSG_08_11_INT_NUM      195U
#define CAN_MOD_ID_4_MSG_12_15_INT_NUM      196U
#define CAN_MOD_ID_4_MSG_16_31_INT_NUM      197U
#define CAN_MOD_ID_4_MSG_32_63_INT_NUM      198U

#define CAN_MOD_ID_5_ESR_ERROR_INT_NUM      202U
#define CAN_MOD_ID_5_ESR_BUS_OFF_INT_NUM    203U
#define CAN_MOD_ID_5_MSG_00_03_INT_NUM      205U
#define CAN_MOD_ID_5_MSG_04_07_INT_NUM      206U
#define CAN_MOD_ID_5_MSG_08_11_INT_NUM      207U
#define CAN_MOD_ID_5_MSG_12_15_INT_NUM      208U
#define CAN_MOD_ID_5_MSG_16_31_INT_NUM      209U
#define CAN_MOD_ID_5_MSG_32_63_INT_NUM      210U


#define CAN_LLD_INTR_ESR_ERROR_NUM(_can_id)   _can_id##_ESR_ERROR_INT_NUM /* PRQA S 0342 # use ## */
#define CAN_LLD_INTR_ESR_BUS_OFF_NUM(_can_id) _can_id##_ESR_BUS_OFF_INT_NUM /* PRQA S 0342 # use ## */
#define CAN_LLD_INTR_MSG_00_03_NUM(_can_id)   _can_id##_MSG_00_03_INT_NUM /* PRQA S 0342 # use ## */
#define CAN_LLD_INTR_MSG_04_07_NUM(_can_id)   _can_id##_MSG_04_07_INT_NUM /* PRQA S 0342 # use ## */
#define CAN_LLD_INTR_MSG_08_11_NUM(_can_id)   _can_id##_MSG_08_11_INT_NUM /* PRQA S 0342 # use ## */
#define CAN_LLD_INTR_MSG_12_15_NUM(_can_id)   _can_id##_MSG_12_15_INT_NUM /* PRQA S 0342 # use ## */
#define CAN_LLD_INTR_MSG_16_31_NUM(_can_id)   _can_id##_MSG_16_31_INT_NUM /* PRQA S 0342 # use ## */
#define CAN_LLD_INTR_MSG_32_63_NUM(_can_id)   _can_id##_MSG_32_63_INT_NUM /* PRQA S 0342 # use ## */

/* CAN interface error code */
#define CAN_OK                     0U
#define CAN_ERROR_INVALID_PARA     1U
#define CAN_ERROR_INVALID_STATE    2U
#define CAN_ERROR_INVALID_MESSAGE  3U
#define CAN_ERROR_MAIL_BOX_ARRANGE 4U
#define CAN_ERROR_MAIL_BOX_ALLOC   5U
#define CAN_ERROR_MAIL_BOX_ABORT   6U
#define CAN_ERROR_MAIL_BOX_STATE   7U
#define CAN_ERROR_MAIL_BOX_EMPTY   8U
#define CAN_ERROR_FIFO_DISABLE     9U
#define CAN_ERROR_FIFO_EMPTY       10U
#define CAN_ERROR_INTR_ARRANGE     11U
#define CAN_ERROR_BUTT             12U

/* CAN module ID */
typedef enum {
    CAN_MOD_ID_0,
    CAN_MOD_ID_1,
    CAN_MOD_ID_2,
    CAN_MOD_ID_3,
    CAN_MOD_ID_4,
    CAN_MOD_ID_5,
    CAN_MOD_BUTT
} CANModId;

typedef enum  {
    CAN_MBPS_1,
    CAN_KBPS_800,
    CAN_KBPS_500,
    CAN_KBPS_250,
    CAN_KBPS_125,
    CAN_KBPS_100,
    CAN_BIT_RATE_BUTT
} CANBitRate;

typedef struct {
    uint32_t cur_msg;
} CanTxMbState;

typedef union {
    uint32_t id;
    struct {
        uint32_t is_valid : 1;
        uint32_t msg_cnt : 31;
    } attr;
} CanTxMbMsgId;

typedef struct {
    uint8_t prop_seg;
    uint8_t time_seg1;
    uint8_t time_seg2;
    uint8_t rjw;
    uint8_t pres_div;
} CANTimeSeg;

typedef struct FLEXCAN_tag volatile CANReg;
typedef struct FLEXCAN_RXFIFO_t volatile CANFifo;

/* CAN RX messages */
typedef struct {
    uint32_t id;
    union {
        uint8_t   byte[8];
        uint32_t  word[2];
    } data;
    uint8_t is_extern;
    uint8_t is_remote;
    uint16_t timestamp;
    uint8_t data_len;
} CANRxMsg;

/* CAN TX message */
typedef struct {
    uint32_t id;
    union {
        uint8_t   byte[8];
        uint32_t  word[2];
    } data;
    uint8_t data_len;
    uint8_t is_extern;
    uint8_t is_remote;
    uint8_t local_prior;
} CANTxMsg;

/* CAN current mode */
typedef enum {
    CAN_CUR_MODE_INIT,
    CAN_CUR_MODE_NORMAL,
    CAN_CUR_MODE_SLEEP,
    CAN_CUR_MODE_FREEZE,
    CAN_CUR_MODE_LISTEN_ONLY,
    CAN_CUR_MODE_LOOP_BACK,
    CAN_CUR_MODE_BUTT
} CANCurMode;

/* CAN error statistics */
typedef struct {
    uint32_t rx_error_cnt;
    uint32_t tx_error_cnt;
    struct {
        uint32_t BIT1ERR:1;
        uint32_t BIT0ERR:1;
        uint32_t ACKERR:1;
        uint32_t CRCERR:1;
        uint32_t FRMERR:1;
        uint32_t STFERR:1;
        uint32_t TXWRN:1;
        uint32_t RXWRN:1;
        uint32_t FLTCONF:2;
    } error_code;
} CANCurError;

/* CAN current status */
typedef struct {
    CANCurMode cur_mode;
    CANCurError cur_error;
} CANState;

/* CAN driver descriptor */
typedef struct {
    CANModId id;
    CANState state;
} CANDriver;

/* CAN protocol Physical layer parameters */
typedef struct {
    uint8_t use_bus_clk_src;
    CANBitRate bit_rate;
} CANPhyPara;

/* CAN function switch */
typedef struct {
    uint8_t bcc_en;
    uint8_t fifo_en;
    uint8_t loop_back_en;
    uint8_t listen_only_en;
} CANFuncSwitch;

/* CAN resource allocation */
typedef struct {
    uint32_t rx_mb_num;
} CANBufConfig;

/* CAN Filter parameter */
typedef struct {
    uint8_t is_remote;//当is_remote为非零值时，表示消息为远程帧；当is_remote为零时，表示消息为数据帧
    uint8_t is_extern;//当is_extern为非零值时，表示消息为扩展标识符帧；当is_extern为零时，表示消息为标准标识符帧。
    uint32_t id;
    uint32_t mask;
} CANFilter;

/* CAN Interrupt callback */
typedef struct {
    void (* tx_mb_msg_transferred)(CANDriver *drv, uint32_t mb_idx);
    void (* tx_mb_msg_aborted)(CANDriver *drv, uint32_t mb_idx);
    void (* rx_mb_msg_received)(CANDriver *drv, uint32_t mb_idx, CANRxMsg *rx_msg);
    void (* rx_fifo_msg_received)(CANDriver *drv, CANRxMsg * rx_msg);
    void (* rx_fifo_msg_almost_full)(CANDriver *drv);
    void (* rx_fifo_msg_truely_full)(CANDriver *drv);
    void (* error)(CANDriver *drv);
    void (* busoff)(CANDriver *drv);
    void (* tx_warning)(CANDriver *drv);
    void (* rx_warning)(CANDriver *drv);
} CANIntrCallback;

/* CAN configuration parameter */
typedef struct {
    CANModId can_id;
    CANPhyPara phy_para;
    CANFuncSwitch func_switch;
    CANBufConfig buf_cfg;
    CANFilter mb[CAN_TOTAL_MAIL_BOX_NUM];
    CANFilter fifo[CAN_FIFO_FILTER_TABLE_NUM];
    CANIntrCallback call_back;
} CANConfig;

static inline uint32_t Can_LLD_Get_FIFO_Use_MB_Num(const CANConfig *config)
{
    return ((uint32_t)config->func_switch.fifo_en != 0U) ? CAN_FIFO_USE_MAIL_BOX_NUM : 0U;
}

#ifndef __GNUC__
static inline uint32_t __builtin_ctz(uint32_t data) /* PRQA S 0602, 3006 # no gcc self-defining function __builtin_ctz */
{
    uint32_t offset;
    /* Generates a carry BIT at the low position */
    data = (~data + 1U) & data; /* PRQA S 1338 # use parameters for efficiency */
    /* Count from high to low 0 */
    __asm__ __volatile__ ("cntlzw %0, %1" : "=b" (offset) : "b" (data)); /* PRQA S 1006 # use asm for efficiency */
    /* Returns the number of zeros from low to high digits */
    return (uint32_t)(31U - offset);
}
#endif

 void Can_LLD_Intr_Msg_Callback(CANModId can_id); /* PRQA S 0554, declaration */
 void Can_LLD_Intr_Err_Callback(CANModId can_id); /* PRQA S 0554, declaration */


#define CAN_LLD_INTR_MSG_HANDLER_NAME(_can_id) Can_LLD_Intr_Msg_Handler_##_can_id /* PRQA S 0342 # use ## */
#define CAN_LLD_INTR_MSG_HANDLER_FUNC(_can_id) static inline void Can_LLD_Intr_Msg_Handler_##_can_id() /* PRQA S 0342, 1029 # use ## */ \
{ \
    Can_LLD_Intr_Msg_Callback(_can_id); \
}

#define CAN_LLD_INTR_ERR_HANDLER_NAME(_can_id) Can_LLD_Intr_Err_Handler_##_can_id /* PRQA S 0342 */
#define CAN_LLD_INTR_ERR_HANDLER_FUNC(_can_id) static inline void Can_LLD_Intr_Err_Handler_##_can_id() /* PRQA S 0342, 1029 # use ## */ \
{ \
    Can_LLD_Intr_Err_Callback(_can_id); \
}

CAN_LLD_INTR_MSG_HANDLER_FUNC(CAN_MOD_ID_0); /* PRQA S 0605, 3007 # macro function */
CAN_LLD_INTR_MSG_HANDLER_FUNC(CAN_MOD_ID_1); /* PRQA S 0605, 3007 # macro function */
CAN_LLD_INTR_MSG_HANDLER_FUNC(CAN_MOD_ID_2); /* PRQA S 0605, 3007 # macro function */
CAN_LLD_INTR_MSG_HANDLER_FUNC(CAN_MOD_ID_3); /* PRQA S 0605, 3007 # macro function */
CAN_LLD_INTR_MSG_HANDLER_FUNC(CAN_MOD_ID_4); /* PRQA S 0605, 3007 # macro function */
CAN_LLD_INTR_MSG_HANDLER_FUNC(CAN_MOD_ID_5); /* PRQA S 0605, 3007 # macro function */

CAN_LLD_INTR_ERR_HANDLER_FUNC(CAN_MOD_ID_0); /* PRQA S 0605, 3007 # macro function */
CAN_LLD_INTR_ERR_HANDLER_FUNC(CAN_MOD_ID_1); /* PRQA S 0605, 3007 # macro function */
CAN_LLD_INTR_ERR_HANDLER_FUNC(CAN_MOD_ID_2); /* PRQA S 0605, 3007 # macro function */
CAN_LLD_INTR_ERR_HANDLER_FUNC(CAN_MOD_ID_3); /* PRQA S 0605, 3007 # macro function */
CAN_LLD_INTR_ERR_HANDLER_FUNC(CAN_MOD_ID_4); /* PRQA S 0605, 3007 # macro function */
CAN_LLD_INTR_ERR_HANDLER_FUNC(CAN_MOD_ID_5); /* PRQA S 0605, 3007 # macro function */

/* can api list*/
CANDriver* Can_LLD_Get_Driver(CANModId can_id);
uint32_t Can_LLD_Init(CANDriver **cand, const CANConfig *config);
uint32_t Can_LLD_DeInit(CANDriver * cand);
uint32_t Can_LLD_Send_Msg(const CANDriver *cand, const CANTxMsg *tx_msg, uint32_t *msg_id);
uint8_t Can_LLD_Is_Msg_Transferred(const CANDriver *cand, uint32_t msg_id);
uint32_t Can_LLD_Abort_Msg_Transfer(const CANDriver *cand, uint32_t msg_id);
uint32_t Can_LLD_Recv_Msg_From_MB(const CANDriver *cand, uint32_t msg_box, CANRxMsg *rx_msg);
uint32_t Can_LLD_Recv_Msg_From_FIFO(const CANDriver *cand, CANRxMsg *rx_msg);
void Can_LLD_Sleep(CANDriver * cand);
void Can_LLD_Wakeup(CANDriver * cand);
 uint32_t Can_LLD_Cfg_Check(const CANConfig *config);
 void Can_LLD_Init_Rx_FIFO(volatile CANReg *reg, const CANConfig *config);
 void Can_LLD_Init_Port(CANModId can_id);
 void Can_LLD_Init_Tx_MB(volatile CANReg *reg, const CANConfig *config);
 void Can_LLD_Init_Rx_MB(volatile CANReg *reg, const CANConfig *config);
 void Can_LLD_Init_Intr(volatile CANReg *reg, const CANConfig *config);
 void Can_LLD_Select_Run_Mode(CANDriver *cand, volatile CANReg *reg, const CANConfig *config);
 void Can_LLD_Config_Clock(CANModId can_id, uint8_t is_enable);
  uint32_t Can_LLD_Alloc_Tx_MB(CANModId can_id);
   uint32_t Can_LLD_Bind_Msg_Id_To_MB(CANModId can_id, uint32_t mb_idx);
   void Can_LLD_Get_Buf_In_FIFO(volatile const CANReg *reg, CANRxMsg *rx_msg);
   uint32_t Can_LLD_Get_Msg_Id_From_MB(CANModId can_id, uint32_t mb_idx);
#endif
